﻿using Newtonsoft.Json;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Xml;

namespace Automation.Data.Helper
{
    public class JsonHelper
    {
        private const string ConfigName_SqlAddress = "SqlAddress";
        public static string timeStyle = "yyyy-MM-dd HH:mm:ss";

        public static string SerializeJson<T>(T obj, int indentation = 0, char indentchar = ' ')
        {
            StringWriter writer = new StringWriter();
            JsonTextWriter jsoonWriter = new JsonTextWriter(writer)
            {
                Formatting = Newtonsoft.Json.Formatting.Indented,
                Indentation = indentation,
                IndentChar = indentchar
            };
            JsonSerializer serializer = new JsonSerializer();
            serializer.Serialize(jsoonWriter, obj);
            return writer.ToString();
        }
        public static T DeserializeJson<T>(string json)
        {
            return JsonConvert.DeserializeObject<T>(json);
        }

        /// <summary>
        /// 将DataTable转换成Entity列表
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static List<T> DataTableToEntityArray<T>(DataTable dataSource, Dictionary<string, string> mapDict = null) where T : new()
        {
            if (dataSource == null || dataSource.Rows.Count == 0)
            {
                return new List<T>();
            }
            List<T> list = new List<T>();
            foreach (DataRow dr in dataSource.Rows)
            {
                T model = new T();
                for (int i = 0; i < dr.Table.Columns.Count; i++)
                {
                    string propertyName = dr.Table.Columns[i].ColumnName;
                    if (mapDict!=null&& mapDict.ContainsKey(propertyName))
                    {
                        propertyName = mapDict[propertyName];
                    }
                    PropertyInfo propertyInfo = model.GetType().GetProperty(propertyName,
    BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
                    if (propertyInfo != null && dr[i] != DBNull.Value)
                    {
                        switch (propertyInfo.PropertyType.Name)
                        {
                            case "bool":
                            case "Boolean":
                                propertyInfo.SetValue(model, (dr[i].ToString() == "1" || dr[i].ToString() == "true"), null);
                                break;
                            case "Int":
                            case "Int32":
                                if (dr[i] != null && !string.IsNullOrEmpty(dr[i].ToString()))
                                    propertyInfo.SetValue(model, int.Parse(dr[i].ToString()), null);
                                break;
                            case "Decimal":
                                if (dr[i] != null && !string.IsNullOrEmpty(dr[i].ToString()))
                                    propertyInfo.SetValue(model, Decimal.Parse(dr[i].ToString()), null);
                                break;
                            case "DateTime":
                                if (dr[i] != null && !string.IsNullOrEmpty(dr[i].ToString()))
                                    propertyInfo.SetValue(model, DateTime.Parse(dr[i].ToString()), null);
                                break;
                            case "String":
                                propertyInfo.SetValue(model, dr[i].ToString(), null);
                                break;
                            case "Nullable`1":
                                var underlyingType = Nullable.GetUnderlyingType(propertyInfo.PropertyType);
                                var value = Convert.ChangeType(dr[i], underlyingType);
                                propertyInfo.SetValue(model, value, null);
                                break;
                            default:
                                propertyInfo.SetValue(model, dr[i].ToString(), null);
                                break;
                        }
                    }
                }
                list.Add(model);
            }
            return list;
        }

        /// <summary>
        /// List to Datatable
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <returns></returns>
        public static DataTable EntityArrayToTable<T>(IEnumerable list)
        {
            if (list == null)
                return default(DataTable);

            //Create a collection of attributes
            List<PropertyInfo> pList = new List<PropertyInfo>();
            //Access to reflection
            Type type = typeof(T);
            DataTable dt = new DataTable();
            //Add all public attributes to the collection and add the columns of datatable
            Array.ForEach<PropertyInfo>(type.GetProperties(), p => { pList.Add(p); dt.Columns.Add(p.Name, p.PropertyType); });
            foreach (var item in list)
            {
                //Create a DataRow instance
                DataRow row = dt.NewRow();
                //Assign a value to row
                pList.ForEach(p => row[p.Name] = p.GetValue(item, null));
                //Add to datatable
                dt.Rows.Add(row);
            }
            return dt;
        }

    }
}
